var serial = {};

(function () {
  "use strict";
  // 获取连接过的设备
  serial.getPorts = function () {
    return navigator.usb.getDevices().then((devices) => {
      return devices.map((device) => new serial.Port(device));
    });
  };
  // 向用户展示不同厂商的USB设备，用户选择后返回具体的设备实例
  serial.requestPort = function () {
    /**
     * vendorId 设备供应商ID
     * productId 产品ID
     * classCode 设备类代码
     * subclassCode 子类代码
     * protocolCode 协议代码
     * serialNumber 设备序列号，同型号的不同设备
     */
    const filters = [
      { vendorId: 0xcafe }, // TinyUSB
      { vendorId: 0x239a }, // Adafruit
      { vendorId: 0x2e8a }, // Raspberry Pi
      { vendorId: 0x303a }, // Espressif
      { vendorId: 0x2341 }, // Arduino
    ];
    return navigator.usb
      .requestDevice({ filters: [] })
      .then((device) => new serial.Port(device));
  };
  // 封装用户选择的设备
  serial.Port = function (device) {
    console.log(device)
    this.device_ = device;
    // 设备接口编号
    this.interfaceNumber = 0;
    // 输入端点编码
    this.endpointIn = 0;
    // 输出端点编码
    this.endpointOut = 0;
  };
  // 连接设备
  serial.Port.prototype.connect = function () {
    let readLoop = () => {
      // 从USB设备接受数据
      // 输入端点编码，最大64字节
      this.device_.transferIn(this.endpointIn, 64).then(
        (result) => {
          this.onReceive(result.data);
          readLoop();
        },
        (error) => {
          this.onReceiveError(error);
        }
      );
    };

    return this.device_
      // 打开设备连接
      .open()
      .then(() => {
        // 选择一个设备配置
        if (this.device_.configuration === null) {
          return this.device_.selectConfiguration(2);
        }
      })
      .then(() => {
        // 设置 -> 配置 -> 接口 -> 端点
        // 配置的接口
        var interfaces = this.device_.configuration.interfaces;
        interfaces.forEach((element) => {
          // 遍历接口的替代设置
          element.alternates.forEach((elementalt) => {
            // 0x01 音频设备
            // 0x03 HID
            // 0x08 大容量存储
            // 0xff 厂商私有协议
            if (elementalt.interfaceClass == 0xff) {
              this.interfaceNumber = element.interfaceNumber;
              // 遍历端点获取端点地址
              elementalt.endpoints.forEach((elementendpoint) => {
                if (elementendpoint.direction == "out") {
                  this.endpointOut = elementendpoint.endpointNumber;
                }
                if (elementendpoint.direction == "in") {
                  this.endpointIn = elementendpoint.endpointNumber;
                }
              });
            }
          });
        });
      })
      // 独占接口
      .then(() => this.device_.claimInterface(this.interfaceNumber))
      .then(() =>
        // 选择接口的替代配置，【一个接口可以有不同的功能配置，即替代配置】
        this.device_.selectAlternateInterface(this.interfaceNumber, 0)
      )
      .then(() =>
        // 发送控制或者配置信息，设置报告事件的频率
        this.device_.controlTransferOut({
          requestType: "class",
          recipient: "interface",
          request: 0x22,
          value: 0x01,
          index: this.interfaceNumber,
        })
      )
      .then(() => {
        readLoop();
      });
  };
  // 断开连接
  serial.Port.prototype.disconnect = function () {
    return this.device_
      .controlTransferOut({
        requestType: "class",
        recipient: "interface",
        request: 0x22,
        value: 0x00,
        index: this.interfaceNumber,
      })
      .then(() => this.device_.close());
  };
  // 发送数据
  serial.Port.prototype.send = function (data) {
    return this.device_.transferOut(this.endpointOut, data);
  };
})();
